#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "esp_event.h"
#include "BSP_WiFi.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "BSP_WiFi.h"
#include "esp_log.h"
#include "TCP.h"
#include "string.h"


#define SERVER_ADDRESS "106.14.10.167"


void tcp_client_task(void *p)
{
    xEventGroupWaitBits(WiFi_EventGroupHandle, WIFI_CONNECT_SUCCESS, pdFALSE, pdFALSE, portMAX_DELAY);
    int time_cnt = 0;
    int _socket;//接字套
    //char hostent_name[] ="time-a.nist.gov"; 
    char  hostent_name[] ="106.14.10.167";
    struct hostent *hostent_add =  gethostbyname(hostent_name);
    char server_buf[BUF_LENGTH];
    if(hostent_add == NULL)
    {
        ESP_LOGI("hostent_add","hostent_add fail");
    }
    else
    {
        
        ESP_LOGI("hostent_add","IP %s",inet_ntoa(*(struct in_addr*)hostent_add->h_addr_list[0]));
    }
create_client_Socket: //连接失败就重新创建  
    _socket = socket(AF_INET,SOCK_STREAM,0);
    if(_socket<0)
    {
        ESP_LOGI("tcp_client_task","Socket fail");
        close(_socket);
        goto create_client_Socket;
    }
    else
    {
        ESP_LOGI("tcp_client_task","Socket Succes");
    }
    
    struct sockaddr_in desk_addr = {
    // 下边这个IP 和端口号是自己设置的，请按需要修改
        //.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr*)hostent_add->h_addr_list[0])),	//ip、
        //.sin_addr.s_addr = inet_addr(inet_ntoa("106.14.10.167")),	//ip 客户端有效
        //.sin_addr.s_addr = inet_addr("");
        .sin_family = AF_INET,
        .sin_port = htons(2222),    // 小端模式转为大端模式 端口号 一般服务器时间获取都是13
    };
    if(inet_pton(AF_INET, SERVER_ADDRESS, &desk_addr.sin_addr) <= 0)
    {
        ESP_LOGI("tcp_client_task", "add err");
    }


    int err;
    err = connect(_socket, (struct sockaddr*)&desk_addr, sizeof(desk_addr));
    if (err == 0){
        ESP_LOGI("tcp_client_task", "Connect Succeed");
        //break;
    }else{
        ESP_LOGI("tcp_client_task", "Connect fail :%d", errno);
        close(_socket);
        //vTaskDelay(pdMS_TO_TICKS(200));
            
        goto create_client_Socket; // goto标签
            
    }
        // int non_blocking,timeout;
        // lwip_ioctl(_socket,FIONBIO,&non_blocking);
        // //设置为非阻塞
        // setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        // //超时接收时间
   
    while (1) 
    {
        //err = send(_socket,sen_p,sizeof(send_),0);
        if(time_cnt < 10) 
        {
            time_cnt++;
        }
        else
        {
           err =  send(_socket,"TCP_R\n",BUF_LENGTH,0);
            time_cnt = 0;
        }
          recv(_socket,server_buf,100,MSG_DONTWAIT);

        if(server_buf[2] == 'g' && server_buf[3] == 'o'&&server_buf[4] == 'g' && server_buf[5] == 'o')
        {
            ESP_LOGI("tcp_client_task","read succeed");
            ESP_LOGI("tcp_client_task","read %s",server_buf);
            memset(server_buf,0x00,BUF_LENGTH);
        }
        if(server_buf[0] == 'e' && server_buf[1] == 'x' && server_buf[2] == 'i' &&server_buf[3] == 't')
        {
            ESP_LOGI("tcp_client_task","connection closed");
            close(_socket);
            vTaskDelete(NULL);
        }
        if(err < 0)
        {
            ESP_LOGI("tcp_client_task","connection error");
            close(_socket);
            goto create_client_Socket;
        }
        
      

        vTaskDelay(pdMS_TO_TICKS(200));
    }
    vTaskDelete(NULL);
}

void tcp_server_task(void*p)
{
    xEventGroupWaitBits(WiFi_EventGroupHandle, WIFI_CONNECT_SUCCESS, pdFALSE, pdFALSE, portMAX_DELAY);
       int server_socket,client_socket;//接字套
create_server_Socket: //连接失败就重新创建  
    server_socket = socket(PF_INET,SOCK_STREAM,0);
    if(server_socket<0)
    {
        ESP_LOGI("tcp_server_task","Socket fail");
        close(server_socket);
        goto create_server_Socket;
    }
    else
    {
        ESP_LOGI("tcp_server_task","Socket Succes");
    }
    
    struct sockaddr_in sevr_addr = {
    // 下边这个IP 和端口号是自己设置的，请按需要修改
        .sin_addr.s_addr = INADDR_ANY,	//ip
        .sin_family = AF_INET,
        .sin_port = htons(1222),    // 小端模式转为大端模式 端口号
    };
    struct sockaddr_in client_addr;
    int err = bind(server_socket,(struct sockaddr*)&sevr_addr,sizeof(sevr_addr));
    if(err == 0)
    {
        ESP_LOGI("tcp_server_task","bind succeed");
    }
    else
    {
        ESP_LOGI("tcp_server_task","bind fail");
        close(server_socket);
        goto create_server_Socket;
    }
    err = listen(server_socket,1);
    if(err == 0)
    {
        ESP_LOGI("tcp_server_task","listen succeed");
    }
    else
    {
        ESP_LOGI("tcp_server_task","listen fail");
        close(server_socket);
        goto create_server_Socket;
    }
    socklen_t client_addr_len;
    client_addr_len = sizeof(client_addr);
    u8_t client_magg[7];
     while(1)
        {
            client_socket = accept(server_socket,(struct sockaddr *)&client_addr,&client_addr_len);
            if(client_socket <0 )
            {
                ESP_LOGI("tcp_server_task","accept fail");
                close(client_socket);
                close(server_socket);
                goto create_server_Socket;
            }
            else
            {
                ESP_LOGI("tcp_server_task","accept succeed");
                break;
            }
        }
        // int non_blocking,timeout;
        // lwip_ioctl(client_socket,FIONBIO,&non_blocking);
        // //设置为非阻塞
        // setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        // //超时接收时间
   
    while(1)
    {
       
        
        err = send(client_socket,"servr\n",7,0);
        if(err == -1)
        {  
            ESP_LOGI("tcp_server_task","send fail");
            close(client_socket);
            close(server_socket);
            goto create_server_Socket;
        }
        else{ ESP_LOGI("tcp_server_task","send succeed");}
        if(recv(client_socket,client_magg,7,0) != 0)
        {
            send(client_socket,client_magg,7,0);
            ESP_LOGI("tcp_server_task","recv succeed");
        }
        ESP_LOGI("tcp_server_task","task");
        //close(client_socket);
        vTaskDelay(pdMS_TO_TICKS(200));
    }
}
